package datastructure;

import java.util.Objects;

public class DLinkListClass<E> {
    private class DLinkNode<E> {
        private DLinkNode prior;
        private E data;
        private DLinkNode next;

        public DLinkNode() {
        }

        public DLinkNode(E e) {
            data = e;
        }

        @Override
        public String toString() {
            return data == null ? "null" : data.toString();
        }
    }

    private DLinkNode<E> head, tail;
    private int size;

    public DLinkListClass() {
        head = new DLinkNode<E>();
        tail = new DLinkNode<E>();
        tail.prior = head;
    }

    @Override
    public String toString() {
        StringBuffer stringBuffer = new StringBuffer("[" + head.toString());
        DLinkNode temp = head.next;
        while (temp != null) {
            stringBuffer.append(" <=> " + temp.toString());
            temp = temp.next;
        }
        stringBuffer.append("]");
        return stringBuffer.toString();
    }

    public void createListF(E[] e) {
        for (int i = 0; i < e.length; i++) {
            DLinkNode temp = new DLinkNode<>(e[i]);
            temp.next = head.next;
            if (head.next != null)
                head.next.prior = temp;
            else
                tail.prior = temp;
            head.next = temp;
            temp.prior = head;
            size++;
        }
    }

    public void createListR(E[] e) {
        size = 0;
        DLinkNode leader = head;
        for (int i = 0; i < e.length; i++) {
            DLinkNode temp = new DLinkNode<>(e[i]);
            leader.next = temp;
            temp.prior = leader;
            leader = temp;
            size++;
        }
        tail.prior = leader;
    }

    public int getSize() {
        return size;
    }

    public int size() {
        int size = 0;
        DLinkNode temp = head;
        while (temp.next != null) {
            temp = temp.next;
            size++;
        }
        return size;
    }

    private DLinkNode getDLinkNode(int index) {
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("LinkListClass.getLinkNode中参数index不合法！");
        else {
            DLinkNode temp;
            if (index <= size / 2) {
                temp = head.next;
                while (index-- > 0) temp = temp.next;
            } else {
                temp = tail.prior;
                while (++index < size) temp = temp.prior;
            }
            return temp;
        }
    }

    public void add(E e) {
        DLinkNode temp = new DLinkNode(e);
        tail.prior.next = temp;
        temp.prior = tail.prior;
        tail.prior = temp;
        size++;
    }

    public E getElement(int index) {
        return (E) getDLinkNode(index).data;
    }

    public void setElement(int index, E e) {
        if (index < 0 || index >= size)
            throw new IllegalArgumentException("LinkListClass.setElement中参数index不合法！");
        getDLinkNode(index).data = e;
    }

    public int getIndex(E e) {
        DLinkNode temp = head.next;
        int count = 0;
        while (temp != null && !Objects.equals(e, temp.data)) {
            temp = temp.next;
            count++;
        }
        return temp == null ? -1 : count;
    }

    public void swap(int index1, int index2) {
        DLinkNode linkNode1 = getDLinkNode(index1);
        DLinkNode linkNode2 = getDLinkNode(index2);
        E temp = (E) linkNode1.data;
        linkNode1.data = linkNode2.data;
        linkNode2.data = temp;
    }

    public void insert(int index, E e) {
        if (index < 0 || index > size) throw new IllegalArgumentException("LinkListClass.insert中参数index不合法！");
        else {
            DLinkNode temp = new DLinkNode(e), leader = index == 0 ? head : getDLinkNode(index - 1);
            temp.next = leader.next;
            if (leader.next != null)
                leader.next.prior = temp;
            tail.prior = leader.next = temp;
            temp.prior = leader;
            size++;
        }
    }

    public void delete(int index) {
        if (index < 0 || index >= size) throw new IllegalArgumentException("LinkListClass.delete中参数index不合法！");
        else {
            DLinkNode temp = getDLinkNode(index);
            if (temp.next != null)
                temp.next.prior = temp.prior;
            temp.prior.next = temp.next;
            size--;
        }
    }

    public void delete(E e) {
        delete(getIndex(e));
    }
}
